﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;

namespace Medianamik.Core.Synchronization
{
    //TODO : Ajouter un argument "messages" aux événements [...]Ended
    //pour indiquer ce qui a "failed"

    public abstract class GenericTypeToRecordTypeConverter<TType, TTypeProperty>
    {
        /// <summary>
        /// Permet la conversion de types génériques en RecordTypes
        /// </summary>
        /// <param name="nodeTypes">Types génériques à convertir</param>
        /// <returns>RecordTypes résultant de la conversion de types génériques</returns>
        public IEnumerable<RecordType> ConvertToRecordTypes(IEnumerable<TType> genericTypes)
        {
            List<TType> typesToConvert = new List<TType>(genericTypes);
            List<RecordType> recordTypes = new List<RecordType>();
            List<TType> skippedTypesToConvert = new List<TType>();
            CancelableMethodResults conversionResult = CancelableMethodResults.Succeeded;

            if (OnConvertingToRecordTypes(typesToConvert))
            {
                conversionResult = CancelableMethodResults.Cancelled;
            }
            else
            {
                int iteration = 1;

                while (conversionResult == CancelableMethodResults.Succeeded && 
                    iteration <= typesToConvert.Count)
                {
                    TType typeToConvert = typesToConvert[iteration - 1];

                    CancelableMethodResult<RecordType> conversion = ConvertToRecordType(typeToConvert,
                        iteration, typesToConvert.Count);

                    switch (conversion.Result)
                    {
                        case CancelableMethodResults.Succeeded:
                            recordTypes.Add(conversion.Data);
                            break;
                        case CancelableMethodResults.Cancelled:
                            skippedTypesToConvert.Add(typeToConvert);
                            break;
                        default: // Failed
                            if (AbortAllOnConvertToRecordTypeFailed)
                                conversionResult = CancelableMethodResults.Failed;
                            else
                                skippedTypesToConvert.Add(typeToConvert);
                            break;
                    }

                    iteration++;
                }
            }

            OnConvertToRecordTypesEnded(typesToConvert, recordTypes, skippedTypesToConvert,
                       conversionResult);

            return recordTypes;
        }

        #region Helper Methods

        /// <summary>
        /// Permet la conversion d'un type générique en un RecordType
        /// </summary>
        /// <param name="typeToConvert">Type générique à convertir</param>
        /// <param name="typeToConvertIndex">L'index du type générique à convertir</param>
        /// <param name="typesToConvertCount">Le nombre total de types à convertir</param>
        /// <returns>RecordType résultant de la conversion d'un type générique</returns>
        private CancelableMethodResult<RecordType> ConvertToRecordType(TType typeToConvert, int typeToConvertIndex,
            int typesToConvertCount)
        {
            RecordType recordType = GetRecordType(typeToConvert);
            CancelableMethodResults conversionResult = CancelableMethodResults.Succeeded;

            if (OnConvertingToRecordType(typeToConvert, typeToConvertIndex, typesToConvertCount))
            {
                conversionResult = CancelableMethodResults.Cancelled;
            }
            else
            {
                bool recordTypeIsValid = true;

                #region Validations

                //TODO : Raise OnConvertToRecordTypeFailed on validation error

                #region Id

                //TODO : Validation

                //if (typeToConvertId == Guid.Empty)
                //    return OnRecordTypeConvertFailed(typeToConvert, typeToConvertIndex,
                //           typesToConvertCount, "Record type id cannot be empty.");

                //if (RecordTypes.Any(rt => rt.Id.Equals(typeToConvertId)))
                //    return OnRecordTypeConvertFailed(typeToConvert, typeToConvertIndex,
                //          typesToConvertCount, "A type with the same id has already been generic.");

                #endregion

                #region Name
                //TODO : Validation

                //if (String.IsNullOrEmpty(typeToConvertName))
                //    return OnRecordTypeConvertFailed(typeToConvert, typeToConvertIndex,
                //        typesToConvertCount, "Record type name cannot be null or empty.");

                //if (RecordTypes.Any(rt => rt.Name.Equals(typeToConvertName, StringComparison.OrdinalIgnoreCase)))
                //    return OnRecordTypeConvertFailed(typeToConvert, typeToConvertIndex,
                //        typesToConvertCount, "A record type with the same name has already been generic.");

                #endregion

                #region Description

                //TODO : Validation

                #endregion

                #region ParentId

                //TODO : Validation

                //if (typeToConvertParentId.HasValue && typeToConvertParentId.Value == Guid.Empty)
                //    return OnRecordTypeConvertFailed(typeToConvert, typeToConvertIndex,
                //        typesToConvertCount, "Record type parent id cannot be empty.");

                #endregion

                #region IconPath

                //TODO : Validation

                #endregion

                #region IsIndexable

                //TODO : Validation

                #endregion

                #region IsSystem

                //TODO : Validation

                #endregion

                #region IsAbstract

                //TODO : Validation

                #endregion

                #region IsGenerated

                //TODO : Validation

                #endregion

                #region IsInheritable

                //TODO : Validation

                #endregion

                #region Properties

                //TODO : S'assurer que les propriétés non pas été ajoutées

                #endregion

                #endregion

                if (recordTypeIsValid)
                {
                    List<TTypeProperty> propertiesToConvert = GetNodeTypeProperties(typeToConvert).ToList();

                    if (propertiesToConvert.Count > 0)
                    {
                        CancelableMethodResult<IEnumerable<RecordTypeProperty>> conversion =
                            ConvertToRecordTypeProperties(propertiesToConvert.AsEnumerable());

                        switch (conversion.Result)
                        {
                            case CancelableMethodResults.Succeeded:
                                recordType.Properties = conversion.Data.ToList();
                                break;
                            case CancelableMethodResults.Cancelled:
                                conversionResult = CancelableMethodResults.Cancelled;
                                break;
                            default: // Failed
                                conversionResult = CancelableMethodResults.Failed;
                                break;
                        }
                    }
                    else
                    {
                        recordType.Properties = new List<RecordTypeProperty>();
                    }
                }
                else
                {
                    conversionResult = CancelableMethodResults.Failed;
                }
            }

            OnConvertToRecordTypeEnded(typeToConvert, recordType, typeToConvertIndex, typesToConvertCount,
                conversionResult);

            return new CancelableMethodResult<RecordType>(conversionResult, recordType);
        }
        
        private CancelableMethodResult<IEnumerable<RecordTypeProperty>> ConvertToRecordTypeProperties(IEnumerable<TTypeProperty> genericProperties)
        {
            List<TTypeProperty> propertiesToConvert = new List<TTypeProperty>(genericProperties);
            List<TTypeProperty> skippedTypeProperties = new List<TTypeProperty>();
            List<RecordTypeProperty> recordTypeProperties = new List<RecordTypeProperty>();
            CancelableMethodResults conversionResult = CancelableMethodResults.Succeeded;

            if (OnConvertingToRecordTypeProperties(propertiesToConvert))
            {
                conversionResult = CancelableMethodResults.Cancelled;
            }
            else
            {
                int iteration = 1;

                while (conversionResult == CancelableMethodResults.Succeeded &&
                    iteration <= propertiesToConvert.Count)
                {
                    TTypeProperty propertyToConvert = propertiesToConvert[iteration - 1];

                    CancelableMethodResult<RecordTypeProperty> conversion = ConvertToRecordTypeProperty(propertyToConvert,
                        iteration, propertiesToConvert.Count);

                    switch (conversion.Result)
                    {
                        case CancelableMethodResults.Succeeded:
                            recordTypeProperties.Add(conversion.Data);
                            break;
                        case CancelableMethodResults.Cancelled:
                            skippedTypeProperties.Add(propertyToConvert);
                            break;
                        default: //Failed
                            if (AbortConvertToRecordTypeOnConvertToRecordTypePropertyFailed)
                            {
                                recordTypeProperties = null;
                                conversionResult = CancelableMethodResults.Failed;
                            }
                            else
                            {
                                skippedTypeProperties.Add(propertyToConvert);
                            }
                            break;
                    }

                    iteration++;
                }
            }

            OnConvertToRecordTypePropertiesEnded(propertiesToConvert, recordTypeProperties,
                skippedTypeProperties, conversionResult);

            return new CancelableMethodResult<IEnumerable<RecordTypeProperty>>(conversionResult,
                recordTypeProperties);
        }

        /// <summary>
        /// Permet la conversion d'une propriété générique d'un type en un RecordTypeProperty
        /// </summary>
        /// <param name="typeToConvert">Propriété générique à convertir</param>
        /// <param name="typeToConvertIndex">L'index de la propriété générique à convertir</param>
        /// <param name="typesToConvertCount">Le nombre total de propriétés à convertir</param>
        /// <returns>RecordTypeProperty résultant de la conversion d'une propriété générique</returns>
        private CancelableMethodResult<RecordTypeProperty> ConvertToRecordTypeProperty(TTypeProperty propertyToConvert,
            int propertyToConvertIndex, int propertiesToConvertCount)
        {
            RecordTypeProperty recordTypeProperty = GetRecordTypeProperty(propertyToConvert);
            CancelableMethodResults conversionResult = CancelableMethodResults.Succeeded;

            if (OnConvertingToRecordTypeProperty(propertyToConvert, propertyToConvertIndex,
                propertiesToConvertCount))
            {
                conversionResult = CancelableMethodResults.Cancelled;
            }
            else
            {
                bool recordTypePropertyIsValid = true;

                #region Validations

                #region Id

                //TODO : Validation

                #endregion

                #region Name

                //if (String.IsNullOrEmpty(genericPropertyName))
                //    return OnRecordTypePropertyConvertFailed(genericProperty, recordType, genericPropertyIndex,
                //        genericPropertiesCount, "Record type property name cannot be null or empty.");

                //if (recordType.Properties.Any(rtp => rtp.Name.Equals(genericPropertyName, StringComparison.OrdinalIgnoreCase)))
                //    return OnRecordTypePropertyConvertFailed(genericProperty, recordType, genericPropertyIndex,
                //        genericPropertiesCount, @"A record type property with the same name has already been added to the type : " + recordType.Name);

                //TODO : Validation

                #endregion

                #region Description

                //TODO : Validation

                #endregion

                #region DataTypeId

                //TODO : Validation

                #endregion

                #region GroupName

                //TODO : Validation

                #endregion

                #region HasTooltip

                //TODO : Validation

                #endregion

                #region IsIndexable

                //TODO : Validation

                #endregion

                #region IsLanguageNeutral

                //TODO : Validation

                #endregion

                #region IsLookup

                //TODO : Validation

                #endregion

                #region IsRequired

                //TODO : Validation

                #endregion

                #region IsUnique

                //TODO : Validation

                #endregion

                #region MaxLength

                //TODO : Validation

                #endregion

                #region MedianamikControlId

                //TODO : Validation

                #endregion

                #region MinLength

                //TODO : Validation

                #endregion

                #region PrimaryDataTypeId

                //TODO : Validation

                #endregion

                #region PrimaryMedianamikControlId

                //TODO : Validation

                #endregion

                #region PrimaryTypeId

                //TODO : Validation

                #endregion

                #region RegexValidation

                //TODO : Validation

                #endregion

                #endregion

                if (!recordTypePropertyIsValid)
                {
                    conversionResult = CancelableMethodResults.Failed;
                }
            }

            OnConvertToRecordTypePropertyEnded(propertyToConvert, recordTypeProperty, propertyToConvertIndex,
                propertiesToConvertCount, conversionResult);

            return new CancelableMethodResult<RecordTypeProperty>(conversionResult,
                recordTypeProperty);
        }

        #endregion

        #region Virtual

        protected virtual bool AbortAllOnConvertToRecordTypeFailed
        {
            get { return true; }
        }

        protected virtual bool AbortConvertToRecordTypeOnConvertToRecordTypePropertyFailed
        {
            get { return true; }
        }

        #endregion

        #region Abstract Members

        public abstract RecordType GetRecordType(TType typeToConvert);
        public abstract RecordTypeProperty GetRecordTypeProperty(TTypeProperty genericProperty);
        public abstract IEnumerable<TTypeProperty> GetNodeTypeProperties(TType type);

        #endregion

        #region Events

        #region RecordTypes

        public event EventHandler<ConvertingToRecordTypesEventArgs<TType>> ConvertingToRecordTypes;
        protected virtual bool OnConvertingToRecordTypes(IList<TType> typesToConvert)
        {
            bool cancel = false;

            EventHandler<ConvertingToRecordTypesEventArgs<TType>> convertingToRecordTypes =
                ConvertingToRecordTypes;

            if (convertingToRecordTypes != null)
            {
                ConvertingToRecordTypesEventArgs<TType> e =
                    new ConvertingToRecordTypesEventArgs<TType>(typesToConvert);
                convertingToRecordTypes(this, e);
                cancel = e.Cancel;
            }

            return cancel;
        }

        public event EventHandler<ConvertToRecordTypesEndedEventArgs<TType>> ConvertToRecordTypesEnded;
        protected virtual void OnConvertToRecordTypesEnded(IEnumerable<TType> typesToConvert,
            IEnumerable<RecordType> recordTypes, IEnumerable<TType> skippedTypesToConvert,
            CancelableMethodResults result)
        {
            EventHandler<ConvertToRecordTypesEndedEventArgs<TType>> convertToRecordTypesEnded =
                ConvertToRecordTypesEnded;

            if (convertToRecordTypesEnded != null)
            {
                ConvertToRecordTypesEndedEventArgs<TType> e =
                    new ConvertToRecordTypesEndedEventArgs<TType>(typesToConvert, recordTypes,
                        skippedTypesToConvert, result);
                convertToRecordTypesEnded(this, e);
            }
        }

        #endregion

        #region RecordType

        public event EventHandler<ConvertingToRecordTypeEventArgs<TType>> ConvertingToRecordType;
        protected virtual bool OnConvertingToRecordType(TType typeToConvert, int typeToConvertIndex,
            int typesToConvertCount)
        {
            bool cancel = false;

            EventHandler<ConvertingToRecordTypeEventArgs<TType>> convertingToRecordType =
                ConvertingToRecordType;

            if (convertingToRecordType != null)
            {
                ConvertingToRecordTypeEventArgs<TType> e =
                    new ConvertingToRecordTypeEventArgs<TType>(typeToConvert, typeToConvertIndex,
                        typesToConvertCount);
                convertingToRecordType(this, e);
                cancel = e.Cancel;
            }

            return cancel;
        }

        public event EventHandler<ConvertToRecordTypeEndedEventArgs<TType>> ConvertToRecordTypeEnded;
        protected virtual void OnConvertToRecordTypeEnded(TType typeToConvert, RecordType recordType,
            int typeToConvertIndex, int typesToConvertCount, CancelableMethodResults result)
        {
            EventHandler<ConvertToRecordTypeEndedEventArgs<TType>> convertToRecordTypeEnded =
                ConvertToRecordTypeEnded;

            if (convertToRecordTypeEnded != null)
            {
                ConvertToRecordTypeEndedEventArgs<TType> e =
                    new ConvertToRecordTypeEndedEventArgs<TType>(typeToConvert, recordType,
                         typeToConvertIndex, typesToConvertCount, result);
                convertToRecordTypeEnded(this, e);
            }
        }

        #endregion

        #region RecordTypeProperties

        public event EventHandler<ConvertingToRecordTypePropertiesEventArgs<TTypeProperty>> ConvertingToRecordTypeProperties;
        protected virtual bool OnConvertingToRecordTypeProperties(IList<TTypeProperty> propertiesToConvert)
        {
            bool cancel = false;

            EventHandler<ConvertingToRecordTypePropertiesEventArgs<TTypeProperty>> convertingToRecordTypeProperties =
                ConvertingToRecordTypeProperties;

            if (convertingToRecordTypeProperties != null)
            {
                ConvertingToRecordTypePropertiesEventArgs<TTypeProperty> e =
                    new ConvertingToRecordTypePropertiesEventArgs<TTypeProperty>(propertiesToConvert);
                convertingToRecordTypeProperties(this, e);
                cancel = e.Cancel;
            }

            return cancel;
        }

        public event EventHandler<ConvertToRecordTypePropertiesEndedEventArgs<TTypeProperty>> ConvertToRecordTypePropertiesEnded;
        protected virtual void OnConvertToRecordTypePropertiesEnded(IEnumerable<TTypeProperty> propertiesToConvert,
            IEnumerable<RecordTypeProperty> recordTypeProperties, IEnumerable<TTypeProperty> skippedTypePropertiesToConvert,
            CancelableMethodResults result)
        {
            EventHandler<ConvertToRecordTypePropertiesEndedEventArgs<TTypeProperty>> convertToRecordTypePropertiesEnded =
                ConvertToRecordTypePropertiesEnded;

            if (convertToRecordTypePropertiesEnded != null)
            {
                ConvertToRecordTypePropertiesEndedEventArgs<TTypeProperty> e =
                    new ConvertToRecordTypePropertiesEndedEventArgs<TTypeProperty>(propertiesToConvert, recordTypeProperties,
                        skippedTypePropertiesToConvert, result);
                convertToRecordTypePropertiesEnded(this, e);
            }
        }

        #endregion

        #region RecordTypeProperty

        public event EventHandler<ConvertingToRecordTypePropertyEventArgs<TTypeProperty>> ConvertingToRecordTypeProperty;
        protected virtual bool OnConvertingToRecordTypeProperty(TTypeProperty propertyToConvert, int propertyToConvertIndex,
            int propertiesToConvertCount)
        {
            bool cancel = false;

            EventHandler<ConvertingToRecordTypePropertyEventArgs<TTypeProperty>> convertingToRecordTypeProperty =
                ConvertingToRecordTypeProperty;

            if (convertingToRecordTypeProperty != null)
            {
                ConvertingToRecordTypePropertyEventArgs<TTypeProperty> e =
                    new ConvertingToRecordTypePropertyEventArgs<TTypeProperty>(propertyToConvert, 
                        propertyToConvertIndex, propertiesToConvertCount);
                convertingToRecordTypeProperty(this, e);
                cancel = e.Cancel;
            }

            return cancel;
        }

        public event EventHandler<ConvertToRecordTypePropertyEndedEventArgs<TTypeProperty>> ConvertToRecordTypePropertyEnded;
        protected virtual void OnConvertToRecordTypePropertyEnded(TTypeProperty propertyToConvert, RecordTypeProperty recordTypeProperty,
            int propertyToConvertIndex, int propertiesToConvertCount, CancelableMethodResults result)
        {
            EventHandler<ConvertToRecordTypePropertyEndedEventArgs<TTypeProperty>> convertToRecordTypePropertyEnded =
                ConvertToRecordTypePropertyEnded;

            if (convertToRecordTypePropertyEnded != null)
            {
                ConvertToRecordTypePropertyEndedEventArgs<TTypeProperty> e =
                    new ConvertToRecordTypePropertyEndedEventArgs<TTypeProperty>(propertyToConvert, recordTypeProperty,
                         propertyToConvertIndex, propertiesToConvertCount, result);
                convertToRecordTypePropertyEnded(this, e);
            }
        }

        #endregion

        #endregion
    }

    public struct CancelableMethodResult<T>
    {
        public CancelableMethodResult(CancelableMethodResults result,
            T data)
        {
            _data = data;
            _result = result;
        }

        public T Data
        {
            get { return _data; }
        }
        T _data;

        public CancelableMethodResults Result
        {
            get { return _result; }
        }
        CancelableMethodResults _result;
    }

    public enum CancelableMethodResults
    {
        Succeeded,
        Failed,
        Cancelled
    }

    #region EventArgs

    #region RecordTypes

    public class ConvertingToRecordTypesEventArgs<T> : CancelEventArgs
    {
        public ConvertingToRecordTypesEventArgs(IList<T> typesToConvert)
        {
            _typesToConvert = typesToConvert;
        }

        #region Properties

        public IList<T> TypesToConvert
        {
            get { return _typesToConvert; }
        }
        IList<T> _typesToConvert;

        #endregion
    }

    public class ConvertToRecordTypesEndedEventArgs<T> : EventArgs
    {
        public ConvertToRecordTypesEndedEventArgs(IEnumerable<T> typesToConvert,
            IEnumerable<RecordType> recordTypes, IEnumerable<T> skippedTypesToConvert,
            CancelableMethodResults result)
        {
            _typesToConvert = typesToConvert;
            _recordTypes = recordTypes;
            _skippedTypesToConvert = skippedTypesToConvert;
            _result = result;
        }

        #region Properties

        public IEnumerable<T> TypesToConvert
        {
            get { return _typesToConvert; }
        }
        IEnumerable<T> _typesToConvert;

        public IEnumerable<RecordType> RecordTypes
        {
            get { return _recordTypes; }
        }
        IEnumerable<RecordType> _recordTypes;

        public IEnumerable<T> SkippedTypesToConvert
        {
            get { return _skippedTypesToConvert; }
        }
        IEnumerable<T> _skippedTypesToConvert;

        public CancelableMethodResults Result
        {
            get { return _result; }
        }
        CancelableMethodResults _result;

        #endregion
    }

    #endregion

    #region RecordType

    public class ConvertingToRecordTypeEventArgs<T> : CancelEventArgs
    {
        public ConvertingToRecordTypeEventArgs(T typeToConvert, int typeToConvertIndex,
            int typesToConvertCount)
        {
            _typeToConvert = typeToConvert;
            _typeToConvertIndex = typeToConvertIndex;
            _typesToConvertCount = typesToConvertCount;
        }

        #region Properties

        public T GenericType
        {
            get
            {
                return _typeToConvert;
            }
        }
        T _typeToConvert;

        public int Index
        {
            get
            {
                return _typeToConvertIndex;
            }
        }
        int _typeToConvertIndex;

        public int NumberOfTypesToConvert
        {
            get { return _typesToConvertCount; }
        }
        int _typesToConvertCount;

        #endregion
    }

    public class ConvertToRecordTypeEndedEventArgs<T> : EventArgs
    {
        public ConvertToRecordTypeEndedEventArgs(T typeToConvert, RecordType recordType,
            int typeToConvertIndex, int typesToConvertCount, CancelableMethodResults result)
        {
            _typeToConvert = typeToConvert;
            _recordType = recordType;
            _result = result;
            _typesToConvertCount = typesToConvertCount;
            _typeToConvertIndex = typeToConvertIndex;
        }

        #region Properties

        public T GenericType
        {
            get
            {
                return _typeToConvert;
            }
        }
        T _typeToConvert;

        public RecordType RecordType
        {
            get { return _recordType; }
        }
        RecordType _recordType;

        public int Index
        {
            get
            {
                return _typeToConvertIndex;
            }
        }
        int _typeToConvertIndex;

        public int NumberOfTypesToConvert
        {
            get { return _typesToConvertCount; }
        }
        int _typesToConvertCount;

        public CancelableMethodResults Result
        {
            get { return _result; }
        }
        CancelableMethodResults _result;

        #endregion
    }

    #endregion

    #region RecordTypeProperties

    public class ConvertingToRecordTypePropertiesEventArgs<T> : CancelEventArgs
    {
        public ConvertingToRecordTypePropertiesEventArgs(IList<T> propertiesToConvert)
        {
            _propertiesToConvert = propertiesToConvert;
        }

        #region Properties

        public IList<T> PropertiesToConvert
        {
            get { return _propertiesToConvert; }
        }
        IList<T> _propertiesToConvert;

        #endregion
    }

    public class ConvertToRecordTypePropertiesEndedEventArgs<T> : EventArgs
    {
        public ConvertToRecordTypePropertiesEndedEventArgs(IEnumerable<T> propertiesToConvert,
            IEnumerable<RecordTypeProperty> recordTypeProperties, IEnumerable<T> skippedTypePropertiesToConvert,
            CancelableMethodResults result)
        {
            _propertiesToConvert = propertiesToConvert;
            _recordTypeProperties = recordTypeProperties;
            _skippedTypePropertiesToConvert = skippedTypePropertiesToConvert;
            _result = result;
        }

        #region Properties

        public IEnumerable<T> TypePropertiesToConvert
        {
            get { return _propertiesToConvert; }
        }
        IEnumerable<T> _propertiesToConvert;

        public IEnumerable<RecordTypeProperty> RecordTypeProperties
        {
            get { return _recordTypeProperties; }
        }
        IEnumerable<RecordTypeProperty> _recordTypeProperties;

        public IEnumerable<T> SkippedTypePropertiesToConvert
        {
            get { return _skippedTypePropertiesToConvert; }
        }
        IEnumerable<T> _skippedTypePropertiesToConvert;

        public CancelableMethodResults Result
        {
            get { return _result; }
        }
        CancelableMethodResults _result;

        #endregion
    }

    #endregion

    #region RecordTypeProperty

    public class ConvertingToRecordTypePropertyEventArgs<T> : CancelEventArgs
    {
        public ConvertingToRecordTypePropertyEventArgs(T propertyToConvert, int propertyToConvertIndex,
            int propertiesToConvertCount)
        {
            _propertyToConvert = propertyToConvert;
            _propertyToConvertIndex = propertyToConvertIndex;
            _propertiesToConvertCount = propertiesToConvertCount;
        }

        #region Properties

        public T GenericProperty
        {
            get
            {
                return _propertyToConvert;
            }
        }
        T _propertyToConvert;

        public int Index
        {
            get
            {
                return _propertyToConvertIndex;
            }
        }
        int _propertyToConvertIndex;

        public int NumberOfPropertyPropertiesToConvert
        {
            get { return _propertiesToConvertCount; }
        }
        int _propertiesToConvertCount;

        #endregion
    }

    public class ConvertToRecordTypePropertyEndedEventArgs<T> : EventArgs
    {
        public ConvertToRecordTypePropertyEndedEventArgs(T propertyToConvert, RecordTypeProperty recordProperty,
            int propertyToConvertIndex, int propertiesToConvertCount, CancelableMethodResults result)
        {
            _propertyToConvert = propertyToConvert;
            _recordProperty = recordProperty;
            _result = result;
            _propertiesToConvertCount = propertiesToConvertCount;
            _propertyToConvertIndex = propertyToConvertIndex;
        }

        #region Properties

        public T GenericProperty
        {
            get
            {
                return _propertyToConvert;
            }
        }
        T _propertyToConvert;

        public RecordTypeProperty RecordTypeProperty
        {
            get { return _recordProperty; }
        }
        RecordTypeProperty _recordProperty;

        public int Index
        {
            get
            {
                return _propertyToConvertIndex;
            }
        }
        int _propertyToConvertIndex;

        public int NumberOfPropertyPropertiesToConvert
        {
            get { return _propertiesToConvertCount; }
        }
        int _propertiesToConvertCount;

        public CancelableMethodResults Result
        {
            get { return _result; }
        }
        CancelableMethodResults _result;

        #endregion
    }

    #endregion

    #endregion
}